//
// Wrapper around XMLHttpRequest which uses a PHP script to wrap
// X-domain requests. 
// 
(function(){

    //ifndef
    if(typeof WrapXHR == 'undefined'){

	/** 
	 * Constant path to PHP wrapper 
	 */
	var WrapXHR = {
	    router:"http://hehi00.nbi.dk:8888/~cholm/castdr/lib/php/wrapxhr.php?url="
	};
	/** 
	 * Beautify logs 
	 */
	var Log = { 
	    e: console.error.bind(console, "%cWrapXHR", "color:#c00"), 
	    w: console.warn.bind(console, "%cWrapXHR", "color:#cc0"), 
	    // i: console.log.bind(console, "%cWrapXHR", "color:#00c")
	    i: function () {}
	};
	/** 
	 * Type of original request 
	 */
	WrapXHR.OrigXHR = XMLHttpRequest;
	/**
	 * Our object 
	 */
	WrapXHR.MyXHR = function (){

	    var onReadyHandler = null;
            var myXHR = this;
            //  WrapXHR.OrigXHR is just the regular XMLHttpRequest
            var origXHR = new WrapXHR.OrigXHR();

            // used in case of regrets :)
            this.regret = function(){
		origXHR = new WrapXHR.OrigXHR();
		origXHR.open.apply(origXHR, myXHR.openArguments);
            }

	    /** 
	     * Overload the open function 
	     */
            this.open = function(){
		Log.i("Open with " + JSON.stringify(arguments));
		myXHR.url = arguments[1];
		// saved in case of regret... :(
		myXHR.openArguments = arguments;
            };

	    /** 
	     * Wrap if X-domain
	     */
            this.checkXD = function(){
		Log.i("Check X-domain " + myXHR.url);
		if(!myXHR.isRelative()){
                    // not a relative url
                    if(!myXHR.hasProtocol()) 
			// now url is 'canonical' with protocol
			myXHR.url = location.protocol + myXHR.url;
                    
                    if(myXHR.isCrossDomain()) {
			// check for cross domain
			// Keep Æ, Ø, and Å
			// var keep = null;
			// if (!(keep = this.doDummy("Æ")))
			// if (!(keep = this.doDummy("Ø")))
			// keep = this.doDummy("Å");			
			var enc = encodeURIComponent(myXHR.url);
			// if (keep) enc = enc.replace("title%3Ddummy",keep);
			// Log.w("Encoding: " + enc + " " + keep);
			myXHR.openArguments[1] = (WrapXHR.router + enc);
		    }
		}
            }
	    this.doDummy = function(c) { 
		var test = "title=" + c;
		if (myXHR.url.indexOf(test) < 0) return null;
		Log.w("Replacing " + test + " with a dummy");
		myXHR.url = myXHR.url.replace(test, "title=dummy");
		test = test.replace("=", "%3D");
		return test;
	    }
	    /** 
	     * Do the real open 
	     */
            this.doOpen = function(){
		Log.i("Do open with " + JSON.stringify(myXHR.openArguments));
		try{
                    origXHR.open.apply(origXHR, myXHR.openArguments);
		}
		catch(error){
		    Log.e("Open failed " + error);
		}
		//
            }
	    /**
	     * Send the request 
	     */
            this.send = function(){
		Log.i("Sending request");
		try{
                    if (!this.withCredentials)	this.checkXD();

                    myXHR.doOpen();
                    while(this.headers.length > 0){
			var header = this.headers.shift();
			var key    = header[0];
			var value  = header[1];
			origXHR.setRequestHeader(key, value);
                    }
                    var ret = origXHR.send(arguments[0] || null);
		    if (myXHR.openArguments[2])  // syncronous 
			Log.i("Got response ret: " + ret);
		}
		catch(error){
		    Log.e("Send failed: " + error);
		}
		return null;
            };
	    /** Possible headers */
            this.headers = [];
	    /** 
	     * Add a request header 
	     */
            this.setRequestHeader = function(){
		this.headers.push(arguments);
            }
	    /** proxify it ~ */
            for (var prop in origXHR){
		if(!myXHR[prop]){
                    // set every XMLHttpRequest property that MyXHR
                    // doesn't override
                    (function(prop){
			if (prop.indexOf('on') == 0) {
                            // XMLHttpRequest callbacks
                            // are assigned MyXHR methods
                            origXHR[prop] = function(){
				if(myXHR[prop]){
                                    return myXHR[prop].apply(myXHR, arguments);
				}
                            }
			}
			else if (typeof origXHR[prop] == 'function'){
                            // all other method of XMLHttpRequest are
                            // proxied by coresponding MyXHR methods
                            myXHR[prop] = function(){
				Log.i("Forwarding to XMLHttpRequest."+prop);
				return origXHR[prop].apply(origXHR, arguments);
                            }
			}
			else {
                            //
                            // all memebers of XMLHttpRequest are
                            // proxied by coresponding MyXHR members
                            Object.defineProperty(myXHR, prop,{
				set: function(value){
                                    origXHR[prop] = value;
				},
				get: function(){
                                    try{
					return origXHR[prop];
                                    }
                                    catch(error){
					Log.e("Error getting property: " 
					      + prop + ": " + error);
                                    }

				}
                            });
			}
                    })(prop);
		}
            }
	};

	/** 
	 * tests for cross domain request
	 * 
	 * @return true if this is a X-domain request
	 */
	WrapXHR.MyXHR.prototype.isCrossDomain = function(){
            var notCrossDomain = 
		RegExp('^' + location.origin.replace(/\./g,'\\.') );
            return !notCrossDomain.test(this.url);
	};
	/** 
	 * Test if we have the protocol part
	 * 
	 * @param url Url.
	 * 
	 * @return true if protocol is present
	 */
	WrapXHR.MyXHR.prototype.hasProtocol = function(url){
            var hasProtocol = RegExp('^https?://');
            return hasProtocol.test(this.url);
	};
	/** 
	 * test for relative urls
	 * 
	 * @param url URL to check
	 * 
	 * @return true if this is a relative url
	 */
	WrapXHR.MyXHR.prototype.isRelative = function(url){
            var notRelative = RegExp('^(https?:)?//');
            return !notRelative.test(this.url);
	};	
	/** 
	 * Turns cross domain sharing ON
	 * 
	 * @return Self
	 */
	WrapXHR.ON = function (){
            if( window.XMLHttpRequest != WrapXHR.MyXHR)
		window.XMLHttpRequest =  WrapXHR.MyXHR;
            return this;
	}	
	/** 
	 * turns cross domain sharing OFF
	 * 
	 * @return Self
	 */
	WrapXHR.OFF = function (){
            if( window.XMLHttpRequest != WrapXHR.OrigXHR )
		window.XMLHttpRequest =  WrapXHR.OrigXHR;
            return this;
	}

	// defualt is on :)
	WrapXHR.ON();
	WrapXHR.setRouter = function(url) { 
	    Log.i("Setting router to " + url);
	    WrapXHR.router = url + "?url=";
	}
	WrapXHR.setDebug = function(on) { 
	    if (on) 
		Log.i = console.log.bind(console, "%cWrapXHR", "color:#00c");
	    else 
		Log.i = function() {}
	}
	window.WrapXHR = WrapXHR;
    }
    //endif
    //console.log("WrapXHR loaded: " + window.WrapXHR);
    //console.log("XMLHttpRequest==WrapXHR.MyXHR: "+XMLHttpRequest==WrapXHR.MyXHR);
})();
// EOF

